package com.hex.ds.hdtp.core.app.script.transfer.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.github.difflib.DiffUtils;
import com.hex.ds.hdtp.core.app.common.page.PageData;
import com.hex.ds.hdtp.core.app.common.page.converter.IPageAndPageDtoConverter;
import com.hex.ds.hdtp.core.app.common.page.dto.PageDto;
import com.hex.ds.hdtp.core.app.common.util.FileEncodeUtil;
import com.hex.ds.hdtp.core.app.data.table.dto.request.TableTransferListRequestDto;
import com.hex.ds.hdtp.core.app.data.table.dto.response.TableTransferListResponseDto;
import com.hex.ds.hdtp.core.app.script.transfer.converter.IScriptConvertSourceListConverter;
import com.hex.ds.hdtp.core.app.script.transfer.dto.request.ScriptConvertSourceListRequestDto;
import com.hex.ds.hdtp.core.app.script.transfer.dto.request.ScriptConvertTaskRequestDto;
import com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertSourceListResponseDto;
import com.hex.ds.hdtp.core.app.script.transfer.service.IScriptConvertOptLogService;
import com.hex.ds.hdtp.core.app.script.transfer.service.IScriptConvertSourceListService;
import com.hex.ds.hdtp.core.app.script.transfer.service.IScriptConvertTaskService;
import com.hex.ds.hdtp.core.inf.common.page.Page;
import com.hex.ds.hdtp.core.inf.data.table.po.TableTransferListPo;
import com.hex.ds.hdtp.core.inf.script.transfer.po.ScriptConvertSourceListPo;
import com.hex.ds.hdtp.core.inf.script.transfer.repository.IScriptConvertSourceListRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FilenameFilter;
import java.util.List;

/**
 * @Package: com.hex.ds.hdtp.core.app.transfer.script.service.impl
 * @ClassName ScriptConvertListService
 * @Description: 脚本转换清单-业务服务接口实现
 * @Author: wz.li
 * @Date 2023/2/12 10:52
 * @Version v2.0.2
 **/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy, @Autowired})
public class ScriptConvertSourceListService implements IScriptConvertSourceListService {

    private final IScriptConvertSourceListRepository scriptConvertListRepository;

    private final IPageAndPageDtoConverter pageAndPageDtoConverter;

    private final IScriptConvertSourceListConverter converter;

    private final IScriptConvertTaskService scriptConvertTaskService;

    private final IScriptConvertOptLogService scriptConvertOptLogService;

    @Value("${script.convert.relativePath}")
    private String relativePath;

    /*
     * @Method: toScriptConvertListPo <br>
     * @Param: [scriptConvertListRequestDto] <br>
     * @Return: com.hex.ds.hdtp.core.inf.script.transfer.po.ScriptConvertListPo <br>
     * @Description：脚本转换清单-requestDto对象转换为PO对象<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:49 <br>
     * @Version： V2.0.2<br>
     */
    private ScriptConvertSourceListPo toScriptConvertListPo(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto) {
        return converter.toScriptConvertListPo(scriptConvertSourceListRequestDto);
    }

    /*
     * @Method: queryListByPage <br>
     * @Param: [scriptConvertListRequestDto, pageDto] <br>
     * @Return: com.hex.ds.hdtp.core.app.common.page.PageData <br>
     * @Description：分页查询<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:50 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public PageData queryListByPage(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto, PageDto pageDto) {
        final Page<ScriptConvertSourceListPo> pageResult = scriptConvertListRepository.queryListByPage(
                toScriptConvertListPo(scriptConvertSourceListRequestDto), pageAndPageDtoConverter.toPage(pageDto));
        List<ScriptConvertSourceListResponseDto> responseDtos = converter.toScriptConvertListResponseDtoList(pageResult.getData());
        return new PageData(responseDtos, pageResult.getTotal());
    }

    /*
     * @Method: add <br>
     * @Param: [scriptConvertListRequestDto] <br>
     * @Return: void <br>
     * @Description：新增<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:50 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void add(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto) {
        int count = scriptConvertListRepository.add(toScriptConvertListPo(scriptConvertSourceListRequestDto));
        if (count != 1) {

        }
    }

    /*
     * @Method: modifyById <br>
     * @Param: [scriptConvertListRequestDto] <br>
     * @Return: void 根据脚本转换清单主键更新<br>
     * @Description：<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:52 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void modifyById(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto) {
        int count = scriptConvertListRepository.modifyById(toScriptConvertListPo(scriptConvertSourceListRequestDto));
        if (count != 1) {

        }
    }

    /*
     * @Method: removeById <br>
     * @Param: [pkId] <br>
     * @Return: void <br>
     * @Description：根据脚本转换清单主键删除<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:51 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void removeById(String pkId) {
        ScriptConvertSourceListPo scriptConvertSourceListPo = scriptConvertListRepository.queryById(pkId);
        removeScriptConvertListData(pkId);
        deleteFile(scriptConvertSourceListPo);
        updateScriptConvertTask(scriptConvertSourceListPo);
    }

    /*
     * @Method: removeScriptConvertListData <br>
     * @Param: [] <br>
     * @Return: void <br>
     * @Description：根据主键删除脚本转换清单数据<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/13 10:54 <br>
     * @Version： V2.0.2<br>
     */
    private void removeScriptConvertListData(String pkId) {
        int count = scriptConvertListRepository.removeById(pkId);
        if (count != 1) {

        }
    }

    /*
     * @Method: deleteFile <br>
     * @Param: [pkId] <br>
     * @Return: void <br>
     * @Description：根据主键删除脚本转换清单文件<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/13 10:55 <br>
     * @Version： V2.0.2<br>
     */
    private void deleteFile(ScriptConvertSourceListPo scriptConvertSourceListPo) {
        File file = new File(scriptConvertSourceListPo.getSourceFilePath() + File.separator + scriptConvertSourceListPo.getSourceFileName());
        if (!file.delete()) {
            throw new RuntimeException("文件删除失败！");
        }
    }

    /*
     * @Method: updateScriptConvertTask <br>
     * @Param: [scriptConvertListPo] <br>
     * @Return: void <br>
     * @Description：更新转换任务信息<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/13 11:01 <br>
     * @Version： V2.0.2<br>
     */
    private void updateScriptConvertTask(ScriptConvertSourceListPo scriptConvertSourceListPo) {
        Integer todoNum = queryByTaskId(scriptConvertSourceListPo.getConvertTaskPkId()).size();
        ScriptConvertTaskRequestDto requestDto = new ScriptConvertTaskRequestDto()
                .setPkId(scriptConvertSourceListPo.getConvertTaskPkId()).setTodoNum(todoNum);
        scriptConvertTaskService.modifyById(requestDto);
    }

    /*
     * @Method: queryListByPageAndSourceFileName <br>
     * @Param: [pkId, sourceFileName, pageDto] <br>
     * @Return: com.hex.ds.hdtp.core.app.common.page.PageData <br>
     * @Description：查询指定文件的转换历史<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:37 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public PageData queryListByPageAndSourceFileName(String pkId, String sourceFileName, PageDto pageDto) {
        final Page<ScriptConvertSourceListPo> pageResult = scriptConvertListRepository.queryListByPage(
                new ScriptConvertSourceListPo().setSourceFileName(sourceFileName), pageAndPageDtoConverter.toPage(pageDto));
        List<ScriptConvertSourceListResponseDto> responseDtos = converter.toScriptConvertListResponseDtoList(pageResult.getData());
        afterQueryListByPage(pkId, responseDtos);
        return new PageData(responseDtos, pageResult.getTotal());
    }

    /*
     * @Method: afterQueryListByPage <br>
     * @Param: [pkId, scriptConvertSourceListResponseDtos] <br>
     * @Return: void <br>
     * @Description：查询指定文件的转换历史 - 数据后置处理<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 17:37 <br>
     * @Version： V2.0.2<br>
     */
    private void afterQueryListByPage(String pkId, List<ScriptConvertSourceListResponseDto> scriptConvertSourceListResponseDtos) {
        ScriptConvertSourceListResponseDto crunScriptConvertList = queryById(pkId);
        for (ScriptConvertSourceListResponseDto scriptConvertList : scriptConvertSourceListResponseDtos) {
            if (FileUtil.exist(scriptConvertList.getSourceFileAbsolutePath()) && FileUtil.exist(crunScriptConvertList.getSourceFileAbsolutePath())) {
                List<String> original = FileUtil.readLines(scriptConvertList.getSourceFileAbsolutePath(), FileEncodeUtil.getFileEncode(scriptConvertList.getSourceFileAbsolutePath()));
                List<String> revised = FileUtil.readLines(crunScriptConvertList.getSourceFileAbsolutePath(), FileEncodeUtil.getFileEncode(crunScriptConvertList.getSourceFileAbsolutePath()));
                scriptConvertList.setIsSourceFileEdit(!DiffUtils.diff(original, revised).getDeltas().isEmpty() ? "Y" : "N");
            }
            scriptConvertList.setIsConvertFileEdit(CollectionUtils.isNotEmpty(scriptConvertOptLogService.queryByScriptConvertListId(scriptConvertList.getPkId())) ? "Y" : "N");
        }
    }

    /*
     * @Method: removeByTaskId <br>
     * @Param: [convertTaskPkId] <br>
     * @Return: void <br>
     * @Description：根据脚本转换任务主键删除转换清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 10:51 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void removeByTaskId(String convertTaskPkId) {
        scriptConvertListRepository.removeByTaskId(convertTaskPkId);
    }

    /*
     * @Method: queryById <br>
     * @Param: [pkId] <br>
     * @Return: com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertListResponseDto <br>
     * @Description：获取指定主键的脚本专家清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/12 18:39 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public ScriptConvertSourceListResponseDto queryById(String pkId) {
        ScriptConvertSourceListPo scriptConvertSourceListPo = scriptConvertListRepository.queryById(pkId);
        ScriptConvertSourceListResponseDto scriptConvertSourceList = converter.toScriptConvertListResponseDto(scriptConvertSourceListPo);
        scriptConvertSourceList.setSourceFileContent(getFileContent(scriptConvertSourceList.getSourceFileAbsolutePath()));
        return scriptConvertSourceList;
    }

    /*
     * @Method: queryConvertHistoryCompareContent <br>
     * @Param: [crunPkId, histPkId] <br>
     * @Return: com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertSourceListResponseDto <br>
     * @Description：获取指定记录与当前最新记录源文件内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/8/16 16:41 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public ScriptConvertSourceListResponseDto queryConvertHistoryCompareContent(String crunPkId, String histPkId) {
        ScriptConvertSourceListResponseDto crunScriptConvertSourceList = queryById(crunPkId);
        ScriptConvertSourceListResponseDto histScriptConvertSourceList = queryById(histPkId);
        crunScriptConvertSourceList.setConvertFileContent(histScriptConvertSourceList.getSourceFileContent());
        return crunScriptConvertSourceList;
    }

    /*
     * @Method: getFileContent <br>
     * @Param: [filePath, fileName] <br>
     * @Return: java.lang.String <br>
     * @Description：获取指定文件内容<br>
     * @Author： wz.li<br>
     * @Date： 2023/6/30 11:23 <br>
     * @Version： V2.0.2<br>
     */
    private String getFileContent(String filePath) {
        String convertFileAbsolutePath = FilenameUtils.separatorsToUnix(filePath);
        if (FileUtil.exist(convertFileAbsolutePath)) {
            return FileUtil.readString(convertFileAbsolutePath, FileEncodeUtil.getFileEncode(convertFileAbsolutePath));
        }
        return "";
    }

    /*
     * @Method: queryByTaskId <br>
     * @Param: [convertTaskPkId] <br>
     * @Return: java.util.List<com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertListResponseDto> <br>
     * @Description：根据指定的转换任务主键查询转换清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/13 11:16 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public List<ScriptConvertSourceListResponseDto> queryByTaskId(String convertTaskPkId) {
        return converter.toScriptConvertListResponseDtoList(scriptConvertListRepository.queryListByTaskId(convertTaskPkId, null));
    }

    /*
     * @Method: modifyByTaskId <br>
     * @Param: [scriptConvertListRequestDto] <br>
     * @Return: java.lang.Integer <br>
     * @Description：根据转换任务主键更新转换清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/13 16:08 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public Integer modifyByTaskId(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto) {
        return scriptConvertListRepository.modifyByTaskId(toScriptConvertListPo(scriptConvertSourceListRequestDto));
    }

    /*
     * @Method: queryByTaskId <br>
     * @Param: [convertTaskPkId, status] <br>
     * @Return: java.util.List<com.hex.ds.hdtp.core.app.script.transfer.dto.response.ScriptConvertListResponseDto> <br>
     * @Description：获取指定任务指定状态转换清单<br>
     * @Author： wz.li<br>
     * @Date： 2023/2/15 14:54 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public List<ScriptConvertSourceListResponseDto> queryByTaskId(String convertTaskPkId, String status) {
        return converter.toScriptConvertListResponseDtoList(scriptConvertListRepository.queryListByTaskId(convertTaskPkId, status));
    }

    /**
     * @Method downloadFile
     * @Param [pkIds]
     * @Return java.lang.String
     * @Description 通过传入的pkid的集合批量下载源文件和转换后文件
     * @Author Guo jiajun
     * @Date 2023/5/10 16:53
     * @Version V1.0
     */
    @Override
    public String downloadFile(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto) {
        //创建打包目录
        String finalPackagePath = getFileRelativePath(relativePath, scriptConvertSourceListRequestDto.getConvertTaskPkId())
                + File.separator + "download-file" + File.separator + DateUtil.current(false);
        File finalPackageDir = new File(finalPackagePath);
        finalPackageDir.mkdirs();
        //复制文件进入打包目录
        downloadFileToPath(scriptConvertSourceListRequestDto, finalPackagePath);
        // 将finalPackageDir打包成一个ZIP文件
        String zipFilePath = finalPackageDir.getAbsolutePath() + ".zip";
        ZipUtil.zip(finalPackagePath, zipFilePath);
        //删除临时文件
        FileUtil.del(finalPackageDir);
        return zipFilePath;
    }


    /**
     * @Method getFileRelativePath
     * @Param [rootPath, converterTaskId]
     * @Return java.lang.String
     * @Description 创建目录
     * @Author Guo jiajun
     * @Date 2023/5/16 22:38
     * @Version V1.0
     */
    private String getFileRelativePath(String rootPath, String converterTaskId) {
        String filePath = rootPath + File.separator + DateUtil.today() + File.separator + converterTaskId;
        FileUtil.mkdir(filePath);
        return filePath;
    }

    /**
     * @Method downloadFileToPath
     * @Param [scriptConvertListRequestDto, finalPackagePath]
     * @Return void
     * @Description
     * @Author Guo jiajun
     * @Date 2023/5/25 17:37
     * @Version V1.0
     */
    public void downloadFileToPath(ScriptConvertSourceListRequestDto scriptConvertSourceListRequestDto, String finalPackagePath) {
        List<ScriptConvertSourceListPo> scriptConvertListPoSourceList = scriptConvertListRepository
                .queryList(converter.toScriptConvertListPo(scriptConvertSourceListRequestDto));
        for (ScriptConvertSourceListPo scriptConvertSourceListPo : scriptConvertListPoSourceList) {
            if (FileUtil.exist(scriptConvertSourceListPo.getSourceFileAbsolutePath()) &&
                    StrUtil.equalsAny(scriptConvertSourceListRequestDto.getDownloadTarget(), "sourceFile", "all")) {
                String targetPath = finalPackagePath + File.separator + scriptConvertSourceListPo.getSourceFileName();
                FileUtil.copyFile(scriptConvertSourceListPo.getSourceFileAbsolutePath(), targetPath);
            }
            if (FileUtil.exist(scriptConvertSourceListPo.getConvertFilePath()) &&
                    StrUtil.equalsAny(scriptConvertSourceListRequestDto.getDownloadTarget(), "convertFile", "all")) {
                for (String convertFileName : getConvertFileNameList(scriptConvertSourceListPo)) {
                    String targetPath = finalPackagePath + File.separator + convertFileName;
                    FileUtil.copy(FilenameUtils.separatorsToUnix(scriptConvertSourceListPo.getConvertFilePath() + File.separator + convertFileName), targetPath, true);
                }
            }
        }
    }

    private String[] getConvertFileNameList(ScriptConvertSourceListPo scriptConvertList) {
        File file = new File(scriptConvertList.getConvertFilePath());
        String[] nameArray = file.list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                String sourceFileName = scriptConvertList.getSourceFileName().substring(0, scriptConvertList.getSourceFileName().indexOf("."));
                String convertFileName = name.substring(0, name.indexOf("."));
                return sourceFileName.equals(convertFileName);
            }
        });
        return nameArray;
    }
}
